package hu.jonas.allunit.handlers;

import hu.jonas.allunit.PluginHelper;
import hu.jonas.allunit.views.AllUnitViewPart;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.junit.launcher.JUnitLaunchShortcut;
import org.eclipse.jface.viewers.StructuredSelection;

public class RunAllTestsHandler extends AbstractHandler {

	private PluginHelper pluginHelper;
	private JUnitLaunchShortcut shortcut;
	private AllUnitViewPart viewPart;

	public RunAllTestsHandler() {
		pluginHelper = new PluginHelper();
		shortcut = new JUnitLaunchShortcut();
	}
	
	protected RunAllTestsHandler(PluginHelper javaCoreHelper) {
		this.pluginHelper = javaCoreHelper;
		viewPart = pluginHelper.getAllUnitView();
	}
	
	@Override
	public Object execute(ExecutionEvent event) throws ExecutionException {
		
		try {
			IWorkspace workspace = pluginHelper.getWorkspace();
			IJavaProject[] javaProjects = pluginHelper.getAllJavaProjects();
			
			int typeCount = 0;
			for (IJavaProject javaProject : javaProjects) {
				if (pluginHelper.hasJavaProjectAllUnitNature(javaProject)) {
					IType[] testTypes = pluginHelper.findTestTypes(javaProject, null);
					typeCount += testTypes.length;
				}
			}
			getViewPart().initializeBeforeRunTests(typeCount);
			
			for (IJavaProject javaProject : javaProjects) {
				if (pluginHelper.hasJavaProjectAllUnitNature(javaProject)) {
					scheduleUnitTests(workspace, javaProject);
				}
			}
		} catch (CoreException e) {
			throw new ExecutionException("Error during running unit tests", e);
		}
		
		return null;
	}
	
	protected void scheduleUnitTests(final IWorkspace workspace, final IJavaProject javaProject) {
		Job unitTests = new Job("Running unit tests for " + javaProject.getElementName()) {

			@Override
			protected IStatus run(IProgressMonitor monitor) {
				pluginHelper.logInfo("Unit tests for %1$s are running", javaProject.getElementName());
				try {
					ILaunchConfiguration[] launchConfigurations =
						shortcut.getLaunchConfigurations(new StructuredSelection(javaProject));
					
					for (ILaunchConfiguration launchConfiguration : launchConfigurations) {
						launchConfiguration.launch(ILaunchManager.RUN_MODE, null);
					}
					pluginHelper.logInfo("Unit tests for %1$s launched", javaProject.getElementName());
				} catch (CoreException e) {
					return new Status(IStatus.ERROR, pluginHelper.getPluginID(), e.getMessage(), e);
				}
				return Status.OK_STATUS;
			}
		};
		
		unitTests.setPriority(Job.BUILD);
		unitTests.schedule();
		pluginHelper.logInfo("Unit tests for %1$s was scheduled", javaProject.getElementName());
	}

	public AllUnitViewPart getViewPart() {
		if (viewPart == null) {
			viewPart = pluginHelper.getAllUnitView();
		}
		return viewPart;
	}
	
}
